package wsi.dataguide.tree;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import org.rygh.core.model.common.MapSet;
import org.rygh.core.xml.XmlObject;
import org.rygh.semantic.gui.swing.input.Input;

public class WSXmlObject extends XmlObject {
	public final static String PREFIX = "uvsq";

	private final XmlObjectOccurrence occurence = new XmlObjectOccurrence();
	private final XmlObjectFunctionality[] functionalities = new XmlObjectFunctionality[4];
	private final MapSet<Input, String> valueMap = new MapSet<>();
	private boolean attribute = false;
	private boolean selected = false;

	public WSXmlObject(String name) {
		this(name, "");
	}

	public WSXmlObject(String name, String value) {
		super(name, value);

		for (int i = 0; i < functionalities.length; i++)
			functionalities[i] = new XmlObjectFunctionality();
	}

	@Override
	public void addAttribute(String key, Object value) {
		super.addAttribute(key, value);

		String val = value.toString();
		XmlObjectOccurrence occur = getOccurence();

		if (key.endsWith("max"))
			occur.setMax(Integer.parseInt(val));
		else if (key.endsWith("min"))
			occur.setMin(Integer.parseInt(val));
		else if (key.endsWith("avg"))
			occur.setAverage(Double.parseDouble(val));
		else if (key.endsWith("isAttribute"))
			attribute = Boolean.parseBoolean(val);
		else if (key.endsWith("isSelected"))
			selected = Boolean.parseBoolean(val);
	}

	public void addValue(Input key, String val) {
		setValue(val);

		if (key != null)
			valueMap.put(key, val);
	}

	public void addValues(Input key, Set<String> values) {
		if (values != null)
			for (String value : values)
				valueMap.put(key, value);
	}

	public XmlObjectFunctionality getCompleteFunctionality() {
		return functionalities[2];
	}

	public XmlObjectFunctionality getCompleteInverseFunctionality() {
		return functionalities[3];
	}

	public XmlObjectFunctionality[] getFunctionalities() {
		return functionalities;
	}

	public XmlObjectFunctionality getFunctionality() {
		return functionalities[0];
	}

	public XmlObjectFunctionality getInverseFunctionality() {
		return functionalities[1];
	}

	public XmlObjectOccurrence getOccurence() {
		return occurence;
	}

	public List<Collection<String>> getValueList() {
		List<Collection<String>> list = new ArrayList<>();

		for (Entry<Input, Set<String>> e : valueMap.entrySet())
			list.add(e.getValue());

		return list;
	}

	public MapSet<Input, String> getValueMap() {
		return valueMap;
	}

	public List<String> getValues() {
		List<String> list = new ArrayList<>();

		for (Entry<Input, Set<String>> e : valueMap.entrySet())
			list.addAll(e.getValue());

		return list;
	}

	public boolean isAttribute() {
		return attribute;
	}

	public boolean isSelected() {
		return selected;
	}

	public void setAttribute(boolean isAttribute) {
		attribute = isAttribute;
	}

	public void setSelected(boolean selected) {
		this.selected = selected;
	}

	public String toDataguideString(int valueLimit) {
		StringBuilder sbuilder = new StringBuilder();

		if (valueLimit == -1) {
			for (Entry<Input, Set<String>> e : valueMap.entrySet()) {
				for (String s : e.getValue())
					sbuilder.append(String.format("%s, ", XmlObject.escape(s)));
			}

		} else if (valueLimit > 0) {
			for (Entry<Input, Set<String>> e : valueMap.entrySet()) {
				Input input = e.getKey();

				/*
				 * we should use entity value, in case there are multiple inputs
				 * with the same literal value. do not forget to escape.
				 */

				sbuilder.append(String.format("<%s:item %s:input=\"%s\">",
						PREFIX, PREFIX,
						XmlObject.escape(input.getEntity().getValue())));

				Object[] _vals = e.getValue().toArray();

				for (int i = 0; i < Math.min(valueLimit, _vals.length); i++)
					sbuilder.append(String.format(
							"<%s:element>%s</%s:element>", PREFIX,
							XmlObject.escape(_vals[i].toString()), PREFIX));

				sbuilder.append(String.format("</%s:item>", PREFIX));
			}
		}

		return sbuilder.toString();
	}

	@Override
	public String toString() {
		return "XmlObject [name=" + name + ", value=" + value + ", max="
				+ occurence.getMax() + "]";
	}

	public String toXmlTagString() {
		return String.format("<%s%s%s%s>", name,
				attribute ? String.format(" %s:isAttribute=\"true\"", PREFIX)
						: "",
				selected ? String.format(" %s:isSelected=\"true\"", PREFIX)
						: "", occurence.toXmlString());
	}
}
